"""
文件上传配置

包含文件上传的所有配置项
"""

import os
from pathlib import Path

# ========== 文件上传配置 ==========

# 上传文件保存目录
UPLOAD_DIR = Path("uploads")
UPLOAD_DIR.mkdir(exist_ok=True)

# 临时文件目录
TEMP_DIR = Path("temp")
TEMP_DIR.mkdir(exist_ok=True)

# 缩略图目录
THUMBNAIL_DIR = UPLOAD_DIR / "thumbnails"
THUMBNAIL_DIR.mkdir(exist_ok=True)

# ========== 文件大小限制 ==========

# 最大文件大小（字节）
MAX_FILE_SIZE = 10 * 1024 * 1024  # 10 MB

# 最大图片大小
MAX_IMAGE_SIZE = 5 * 1024 * 1024  # 5 MB

# 最大视频大小
MAX_VIDEO_SIZE = 50 * 1024 * 1024  # 50 MB

# 最大文档大小
MAX_DOCUMENT_SIZE = 10 * 1024 * 1024  # 10 MB

# ========== 允许的文件类型 ==========

# 允许的图片格式
ALLOWED_IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"}
ALLOWED_IMAGE_MIMETYPES = {
    "image/jpeg",
    "image/png",
    "image/gif",
    "image/webp",
    "image/bmp",
}

# 允许的文档格式
ALLOWED_DOCUMENT_EXTENSIONS = {".pdf", ".doc", ".docx", ".txt", ".xlsx", ".xls", ".ppt", ".pptx"}
ALLOWED_DOCUMENT_MIMETYPES = {
    "application/pdf",
    "application/msword",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    "text/plain",
    "application/vnd.ms-excel",
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "application/vnd.ms-powerpoint",
    "application/vnd.openxmlformats-officedocument.presentationml.presentation",
}

# 允许的视频格式
ALLOWED_VIDEO_EXTENSIONS = {".mp4", ".avi", ".mov", ".wmv", ".flv", ".webm"}
ALLOWED_VIDEO_MIMETYPES = {
    "video/mp4",
    "video/x-msvideo",
    "video/quicktime",
    "video/x-ms-wmv",
    "video/x-flv",
    "video/webm",
}

# 允许的音频格式
ALLOWED_AUDIO_EXTENSIONS = {".mp3", ".wav", ".ogg", ".flac", ".aac"}
ALLOWED_AUDIO_MIMETYPES = {
    "audio/mpeg",
    "audio/wav",
    "audio/ogg",
    "audio/flac",
    "audio/aac",
}

# ========== 图片处理配置 ==========

# 缩略图尺寸
THUMBNAIL_SIZES = {
    "small": (150, 150),
    "medium": (300, 300),
    "large": (600, 600),
}

# 图片质量（1-100）
IMAGE_QUALITY = 85

# 是否保持宽高比
KEEP_ASPECT_RATIO = True

# ========== 文件命名配置 ==========

# 是否使用 UUID 重命名文件
USE_UUID_FILENAME = True

# 文件名最大长度
MAX_FILENAME_LENGTH = 255

# ========== 安全配置 ==========

# 是否检查文件内容（而不仅仅是扩展名）
CHECK_FILE_CONTENT = True

# 是否扫描病毒（需要集成第三方服务）
ENABLE_VIRUS_SCAN = False

# ========== URL 配置 ==========

# 文件访问基础 URL
FILE_BASE_URL = "/files"

# ========== 辅助函数 ==========

def get_upload_path(filename: str, subdir: str = "") -> Path:
    """
    获取文件上传路径
    
    Args:
        filename: 文件名
        subdir: 子目录
        
    Returns:
        完整的文件路径
    """
    if subdir:
        path = UPLOAD_DIR / subdir
        path.mkdir(exist_ok=True)
        return path / filename
    return UPLOAD_DIR / filename


def get_thumbnail_path(filename: str, size: str = "medium") -> Path:
    """
    获取缩略图路径
    
    Args:
        filename: 原文件名
        size: 缩略图尺寸（small/medium/large）
        
    Returns:
        缩略图路径
    """
    size_dir = THUMBNAIL_DIR / size
    size_dir.mkdir(exist_ok=True)
    return size_dir / filename


def is_allowed_file_type(filename: str, file_type: str) -> bool:
    """
    检查文件类型是否允许
    
    Args:
        filename: 文件名
        file_type: 文件类型（image/document/video/audio）
        
    Returns:
        是否允许
    """
    ext = Path(filename).suffix.lower()
    
    type_extensions = {
        "image": ALLOWED_IMAGE_EXTENSIONS,
        "document": ALLOWED_DOCUMENT_EXTENSIONS,
        "video": ALLOWED_VIDEO_EXTENSIONS,
        "audio": ALLOWED_AUDIO_EXTENSIONS,
    }
    
    allowed_extensions = type_extensions.get(file_type, set())
    return ext in allowed_extensions


def get_max_file_size(file_type: str) -> int:
    """
    获取指定类型文件的最大大小
    
    Args:
        file_type: 文件类型
        
    Returns:
        最大字节数
    """
    size_map = {
        "image": MAX_IMAGE_SIZE,
        "document": MAX_DOCUMENT_SIZE,
        "video": MAX_VIDEO_SIZE,
        "audio": MAX_FILE_SIZE,
    }
    return size_map.get(file_type, MAX_FILE_SIZE)


def format_file_size(size_bytes: int) -> str:
    """
    格式化文件大小
    
    Args:
        size_bytes: 字节数
        
    Returns:
        格式化的字符串（如 "1.5 MB"）
    """
    for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
        if size_bytes < 1024.0:
            return f"{size_bytes:.2f} {unit}"
        size_bytes /= 1024.0
    return f"{size_bytes:.2f} PB"

